This notebook will begin looking at clustering methods on the expression of the genes in a single sample of the dataset of interest, from an unbiased approach.

Set Up

# Load libraries
library(magrittr)
library(scater)
library(readr)
library(bluster)
library(ggpubr)
library(pheatmap)

# Set file paths
data_dir <- file.path("results", "Gawad_processed_data")

# Source custom functions script
source(file.path("utils", "clustering-functions.R"))

Read in data

sample_290_normalized <- read_rds(
  file.path(data_dir, "SCPCS000216", "SCPCL000290_miQC_downstream_processed_normalized_reduced_sce.rds"))

Perform clustering

k-means

# Perform k-means clustering
kmeans_cluster_names <- paste0("kcluster", c(2:15))

sample_290_normalized <- kmeans_clustering(
  sample_290_normalized,
  k_range = c(2:15),
  check_stability = TRUE
)

# Plot k-means
kmeans_plot_list <- kmeans_cluster_names %>%
  purrr::map(~ plotReducedDim(sample_290_normalized, dimred = "UMAP", colour_by = .x))

cowplot::plot_grid(plotlist = kmeans_plot_list, ncol = 4)

graph-based, walktrap

# Perform graph-based walktrap clustering
walktrap_cluster_names <-paste0("walktrap_cluster", c(5, 10, 15, 20, 25, 50, 100))

sample_290_normalized <- graph_clustering(
  sample_290_normalized,
  nn_range = c(5, 10, 15, 20, 25, 50, 100),
  weighting_type = "rank",
  cluster_function = "walktrap",
  check_stability = TRUE
)
detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'
# Plot
walktrap_plot_list <- walktrap_cluster_names %>%
   purrr::map(~ plotReducedDim(sample_290_normalized, dimred = "UMAP", colour_by = .x))

cowplot::plot_grid(plotlist = walktrap_plot_list, ncol = 3)

graph-based, louvain

# Perform graph-based louvain clustering
louvain_cluster_names <- paste0("louvain_cluster", c(5, 10, 15, 20, 25, 50, 100))

sample_290_normalized <- graph_clustering(
  sample_290_normalized,
  nn_range = c(5, 10, 15, 20, 25, 50, 100),
  weighting_type = "jaccard",
  cluster_function = "louvain",
  check_stability = TRUE
)
detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'detected tied distances to neighbors, see ?'BiocNeighbors-ties'
# Plot
louvain_plot_list <- louvain_cluster_names %>%
   purrr::map(~ plotReducedDim(sample_290_normalized, dimred = "UMAP", colour_by = .x))


cowplot::plot_grid(plotlist = louvain_plot_list, ncol = 3)

Check cluster validity stats

k-means

# Preview the saved results
write_tsv(metadata(sample_290_normalized)$all_stats$kmeans, file.path = ("example_stats.tsv"))
Error in write_tsv(metadata(sample_290_normalized)$all_stats$kmeans, file.path = ("example_stats.tsv")) : 
  unused argument (file.path = ("example_stats.tsv"))

purity plots

# Plot individual cluster and summary stats
kmeans_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$kmeans,
                         metadata(sample_290_normalized)$summary_stats$kmeans,
                         "purity", "maximum", "cluster_names", c(2:15))
Outer names are only allowed for unnamed scalar atomic inputs
kmeans_plots

silhouette width plots

# Plot individual cluster and summary stats
kmeans_silhouette_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$kmeans,
                         metadata(sample_290_normalized)$summary_stats$kmeans,
                         "width", "closest", "cluster_names", c(2:15))
Outer names are only allowed for unnamed scalar atomic inputs
kmeans_silhouette_plots

graph-based, walktrap

# Check the walktrap cluster validity stats for each of the clusters and produce
# a summary data frame of these stats to be stored within the SCE object
sample_290_normalized <- add_metadata_clustering_stats(sample_290_normalized, walktrap_cluster_names, "walktrap")
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
Joining, by = "cell_barcode"
  
# Preview the saved results
head(metadata(sample_290_normalized)$all_stats$walktrap)

# Preview the saved summary results
head(metadata(sample_290_normalized)$summary_stats$walktrap)

purity plots

# Plot individual cluster and summary stats
walktrap_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$walktrap,
                         metadata(sample_290_normalized)$summary_stats$walktrap,
                         "purity", "maximum", "cluster_names", c(5, 10, 15, 20, 25, 50, 100))
Outer names are only allowed for unnamed scalar atomic inputs
walktrap_plots

silhouette width plots

# Plot individual cluster and summary stats
walktrap_silhouette_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$walktrap,
                         metadata(sample_290_normalized)$summary_stats$walktrap,
                         "width", "closest", "cluster_names", c(5, 10, 15, 20, 25, 50, 100))
Outer names are only allowed for unnamed scalar atomic inputs
walktrap_silhouette_plots

graph-based, louvain

purity plots

# Plot individual cluster and summary stats
louvain_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$louvain,
                         metadata(sample_290_normalized)$summary_stats$louvain,
                         "purity", "maximum", "cluster_names", c(5, 10, 15, 20, 25, 50, 100))
Outer names are only allowed for unnamed scalar atomic inputs
louvain_plots

silhouette width plots

# Plot individual cluster and summary stats
louvain_silhouette_plots <- plot_clustering_validity(metadata(sample_290_normalized)$all_stats$louvain,
                         metadata(sample_290_normalized)$summary_stats$louvain,
                         "width", "closest", "cluster_names", c(5, 10, 15, 20, 25, 50, 100))
Outer names are only allowed for unnamed scalar atomic inputs
louvain_silhouette_plots

Check cluster stability

k-means

# Check and plot cluster stability CDF
cdf <- NULL
for (name in kmeans_cluster_names) {
  cdf[[name]] <- prepare_plot_cluster_stability(sample_290_normalized, name)
}

colors <- palette.colors(palette = "Okabe-Ito")

plot(cdf[["kcluster2"]], verticals=TRUE, do.points=FALSE, main = "kcluster cluster stability CDF")
plot(cdf[["kcluster3"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[1])
plot(cdf[["kcluster4"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[2])
plot(cdf[["kcluster5"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[3])
plot(cdf[["kcluster6"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[4])
plot(cdf[["kcluster7"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[5])
plot(cdf[["kcluster8"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[6])
plot(cdf[["kcluster9"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[7])
plot(cdf[["kcluster10"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[8])
plot(cdf[["kcluster11"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[9])
plot(cdf[["kcluster12"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[10])
plot(cdf[["kcluster13"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[11])
plot(cdf[["kcluster14"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[12])
plot(cdf[["kcluster15"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[13])
legend(0.65, 0.95, legend = as.list(kmeans_cluster_names), col = colors, cex = 0.5, pch = 15)

graph-based, walktrap

# Check and plot cluster stability CDF
cdf <- NULL
for (name in walktrap_cluster_names) {
  cdf[[name]] <- prepare_plot_cluster_stability(sample_290_normalized, name)
}

colors <- palette.colors(palette = "Okabe-Ito")[2:length(walktrap_cluster_names) + 1]

plot(cdf[["walktrap_cluster5"]], verticals=TRUE, do.points=FALSE, main = "walktrap cluster stability CDF")
plot(cdf[["walktrap_cluster10"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[1])
plot(cdf[["walktrap_cluster15"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[2])
plot(cdf[["walktrap_cluster20"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[3])
plot(cdf[["walktrap_cluster25"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[4])
plot(cdf[["walktrap_cluster50"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[5])
plot(cdf[["walktrap_cluster100"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[6])
legend(-3, 0.95, legend = as.list(walktrap_cluster_names), col = colors, cex = 0.5, pch = 15)

graph-based, louvain

# Check and plot cluster stability CDF
cdf <- NULL
for (name in louvain_cluster_names) {
  cdf[[name]] <- prepare_plot_cluster_stability(sample_290_normalized, name)
}

colors <- palette.colors(palette = "Okabe-Ito")[2:length(louvain_cluster_names) + 1]

plot(cdf[["louvain_cluster5"]], verticals=TRUE, do.points=FALSE, main = "louvain cluster stability CDF")
plot(cdf[["louvain_cluster10"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[1])
plot(cdf[["louvain_cluster15"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[2])
plot(cdf[["louvain_cluster20"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[3])
plot(cdf[["louvain_cluster25"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[4])
plot(cdf[["louvain_cluster50"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[5])
plot(cdf[["louvain_cluster100"]], verticals=TRUE, do.points=FALSE, add=TRUE, col=colors[6])
legend(-0.25, 0.95, legend = as.list(louvain_cluster_names), col = colors, cex = 0.5, pch = 15)

Session info

sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.3 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so

locale:
 [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8        LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8   
 [6] LC_MESSAGES=C.UTF-8    LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C           LC_TELEPHONE=C        
[11] LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   

attached base packages:
[1] grid      stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] pheatmap_1.0.12             ggpubr_0.4.0                bluster_1.4.0               HDF5Array_1.22.1           
 [5] rhdf5_2.38.0                DelayedArray_0.20.0         Matrix_1.3-4                ComplexHeatmap_2.10.0      
 [9] scater_1.22.0               ggplot2_3.3.5               scuttle_1.4.0               SingleCellExperiment_1.16.0
[13] SummarizedExperiment_1.24.0 Biobase_2.54.0              GenomicRanges_1.46.1        GenomeInfoDb_1.30.0        
[17] IRanges_2.28.0              S4Vectors_0.32.3            BiocGenerics_0.40.0         MatrixGenerics_1.6.0       
[21] matrixStats_0.61.0          readr_2.1.1                 magrittr_2.0.1             

loaded via a namespace (and not attached):
  [1] ggbeeswarm_0.6.0          colorspace_2.0-2          ggsignif_0.6.3            rjson_0.2.20              ellipsis_0.3.2           
  [6] modeltools_0.2-23         circlize_0.4.13           XVector_0.34.0            GlobalOptions_0.1.2       BiocNeighbors_1.12.0     
 [11] rstudioapi_0.13           clue_0.3-60               farver_2.1.0              ggrepel_0.9.1             flexmix_2.3-17           
 [16] fansi_0.5.0               codetools_0.2-18          splines_4.1.2             sparseMatrixStats_1.6.0   doParallel_1.0.16        
 [21] knitr_1.36                polyclip_1.10-0           broom_0.7.10              cluster_2.1.2             png_0.1-7                
 [26] ggforce_0.3.3             compiler_4.1.2            backports_1.4.0           assertthat_0.2.1          fastmap_1.1.0            
 [31] cli_3.1.0                 tweenr_1.0.2              BiocSingular_1.10.0       miQC_1.2.0                htmltools_0.5.2          
 [36] tools_4.1.2               rsvd_1.0.5                igraph_1.2.9              gtable_0.3.0              glue_1.5.1               
 [41] GenomeInfoDbData_1.2.7    dplyr_1.0.7               Rcpp_1.0.7                carData_3.0-4             vctrs_0.3.8              
 [46] rhdf5filters_1.6.0        iterators_1.0.13          DelayedMatrixStats_1.16.0 xfun_0.28                 beachmat_2.10.0          
 [51] lifecycle_1.0.1           irlba_2.3.3               renv_0.14.0               rstatix_0.7.0             MASS_7.3-54              
 [56] zlibbioc_1.40.0           scales_1.1.1              hms_1.1.1                 parallel_4.1.2            RColorBrewer_1.1-2       
 [61] yaml_2.2.1                gridExtra_2.3             foreach_1.5.1             ScaledMatrix_1.2.0        BiocParallel_1.28.2      
 [66] shape_1.4.6               rlang_0.4.12              pkgconfig_2.0.3           bitops_1.0-7              evaluate_0.14            
 [71] lattice_0.20-45           purrr_0.3.4               Rhdf5lib_1.16.0           labeling_0.4.2            cowplot_1.1.1            
 [76] tidyselect_1.1.1          R6_2.5.1                  generics_0.1.1            DBI_1.1.1                 pillar_1.6.4             
 [81] withr_2.4.3               abind_1.4-5               RCurl_1.98-1.5            nnet_7.3-16               tibble_3.1.6             
 [86] crayon_1.4.2              car_3.0-12                utf8_1.2.2                tzdb_0.2.0                rmarkdown_2.11           
 [91] viridis_0.6.2             GetoptLong_1.0.5          data.table_1.14.2         forcats_0.5.1             digest_0.6.29            
 [96] tidyr_1.1.4               munsell_0.5.0             beeswarm_0.4.0            viridisLite_0.4.0         vipor_0.4.5              
LS0tCnRpdGxlOiAiQ2x1c3RlcmluZyIKYXV0aG9yOiBEYXRhIExhYiBmb3IgQUxTRgpkYXRlOiAyMDIyCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKVGhpcyBub3RlYm9vayB3aWxsIGJlZ2luIGxvb2tpbmcgYXQgY2x1c3RlcmluZyBtZXRob2RzIG9uIHRoZSBleHByZXNzaW9uIG9mIHRoZSBnZW5lcyBpbiBhIHNpbmdsZSBzYW1wbGUgb2YgdGhlIGRhdGFzZXQgb2YgaW50ZXJlc3QsIGZyb20gYW4gdW5iaWFzZWQgYXBwcm9hY2guCgojIyBTZXQgVXAgCgpgYGB7cn0KIyBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KHNjYXRlcikKbGlicmFyeShyZWFkcikKbGlicmFyeShibHVzdGVyKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShwaGVhdG1hcCkKCiMgU2V0IGZpbGUgcGF0aHMKZGF0YV9kaXIgPC0gZmlsZS5wYXRoKCJyZXN1bHRzIiwgIkdhd2FkX3Byb2Nlc3NlZF9kYXRhIikKCiMgU291cmNlIGN1c3RvbSBmdW5jdGlvbnMgc2NyaXB0CnNvdXJjZShmaWxlLnBhdGgoInV0aWxzIiwgImNsdXN0ZXJpbmctZnVuY3Rpb25zLlIiKSkKYGBgCgojIyBSZWFkIGluIGRhdGEKCmBgYHtyfQpzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gcmVhZF9yZHMoCiAgZmlsZS5wYXRoKGRhdGFfZGlyLCAiU0NQQ1MwMDAyMTYiLCAiU0NQQ0wwMDAyOTBfbWlRQ19kb3duc3RyZWFtX3Byb2Nlc3NlZF9ub3JtYWxpemVkX3JlZHVjZWRfc2NlLnJkcyIpKQpgYGAKCiMjIFBlcmZvcm0gY2x1c3RlcmluZwoKIyMjIGstbWVhbnMKCmBgYHtyIGZpZy5oZWlnaHQgPSAxMC41fQojIFBlcmZvcm0gay1tZWFucyBjbHVzdGVyaW5nCmttZWFuc19jbHVzdGVyX25hbWVzIDwtIHBhc3RlMCgia2NsdXN0ZXIiLCBjKDI6MTUpKQoKc2FtcGxlXzI5MF9ub3JtYWxpemVkIDwtIGttZWFuc19jbHVzdGVyaW5nKAogIHNhbXBsZV8yOTBfbm9ybWFsaXplZCwKICBrX3JhbmdlID0gYygyOjE1KSwKICBjaGVja19zdGFiaWxpdHkgPSBUUlVFCikKCiMgUGxvdCBrLW1lYW5zCmttZWFuc19wbG90X2xpc3QgPC0ga21lYW5zX2NsdXN0ZXJfbmFtZXMgJT4lCiAgcHVycnI6Om1hcCh+IHBsb3RSZWR1Y2VkRGltKHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgZGltcmVkID0gIlVNQVAiLCBjb2xvdXJfYnkgPSAueCkpCgpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBrbWVhbnNfcGxvdF9saXN0LCBuY29sID0gNCkKYGBgCgojIyMgZ3JhcGgtYmFzZWQsIHdhbGt0cmFwCgpgYGB7ciBmaWcuaGVpZ2h0ID0gOS41fQojIFBlcmZvcm0gZ3JhcGgtYmFzZWQgd2Fsa3RyYXAgY2x1c3RlcmluZwp3YWxrdHJhcF9jbHVzdGVyX25hbWVzIDwtcGFzdGUwKCJ3YWxrdHJhcF9jbHVzdGVyIiwgYyg1LCAxMCwgMTUsIDIwLCAyNSwgNTAsIDEwMCkpCgpzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gZ3JhcGhfY2x1c3RlcmluZygKICBzYW1wbGVfMjkwX25vcm1hbGl6ZWQsCiAgbm5fcmFuZ2UgPSBjKDUsIDEwLCAxNSwgMjAsIDI1LCA1MCwgMTAwKSwKICB3ZWlnaHRpbmdfdHlwZSA9ICJyYW5rIiwKICBjbHVzdGVyX2Z1bmN0aW9uID0gIndhbGt0cmFwIiwKICBjaGVja19zdGFiaWxpdHkgPSBUUlVFCikKCiMgUGxvdAp3YWxrdHJhcF9wbG90X2xpc3QgPC0gd2Fsa3RyYXBfY2x1c3Rlcl9uYW1lcyAlPiUKICAgcHVycnI6Om1hcCh+IHBsb3RSZWR1Y2VkRGltKHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgZGltcmVkID0gIlVNQVAiLCBjb2xvdXJfYnkgPSAueCkpCgpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSB3YWxrdHJhcF9wbG90X2xpc3QsIG5jb2wgPSAzKQpgYGAKCiMjIyBncmFwaC1iYXNlZCwgbG91dmFpbgoKYGBge3IgZmlnLmhlaWdodCA9IDguNX0KIyBQZXJmb3JtIGdyYXBoLWJhc2VkIGxvdXZhaW4gY2x1c3RlcmluZwpsb3V2YWluX2NsdXN0ZXJfbmFtZXMgPC0gcGFzdGUwKCJsb3V2YWluX2NsdXN0ZXIiLCBjKDUsIDEwLCAxNSwgMjAsIDI1LCA1MCwgMTAwKSkKCnNhbXBsZV8yOTBfbm9ybWFsaXplZCA8LSBncmFwaF9jbHVzdGVyaW5nKAogIHNhbXBsZV8yOTBfbm9ybWFsaXplZCwKICBubl9yYW5nZSA9IGMoNSwgMTAsIDE1LCAyMCwgMjUsIDUwLCAxMDApLAogIHdlaWdodGluZ190eXBlID0gImphY2NhcmQiLAogIGNsdXN0ZXJfZnVuY3Rpb24gPSAibG91dmFpbiIsCiAgY2hlY2tfc3RhYmlsaXR5ID0gVFJVRQopCgojIFBsb3QKbG91dmFpbl9wbG90X2xpc3QgPC0gbG91dmFpbl9jbHVzdGVyX25hbWVzICU+JQogICBwdXJycjo6bWFwKH4gcGxvdFJlZHVjZWREaW0oc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBkaW1yZWQgPSAiVU1BUCIsIGNvbG91cl9ieSA9IC54KSkKCgpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBsb3V2YWluX3Bsb3RfbGlzdCwgbmNvbCA9IDMpCmBgYAoKIyMgQ2hlY2sgY2x1c3RlciB2YWxpZGl0eSBzdGF0cwoKIyMjIGstbWVhbnMKCmBgYHtyIGZpZy5oZWlnaHQgPSAyMC41fQojIENoZWNrIHRoZSBrLW1lYW5zIGNsdXN0ZXIgdmFsaWRpdHkgc3RhdHMgZm9yIGVhY2ggb2YgdGhlIGNsdXN0ZXJzIGFuZCBwcm9kdWNlCiMgYSBzdW1tYXJ5IGRhdGEgZnJhbWUgb2YgdGhlc2Ugc3RhdHMgdG8gYmUgc3RvcmVkIHdpdGhpbiB0aGUgU0NFIG9iamVjdApzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gYWRkX21ldGFkYXRhX2NsdXN0ZXJpbmdfc3RhdHMoc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBrbWVhbnNfY2x1c3Rlcl9uYW1lcywgImttZWFucyIpCgojIFByZXZpZXcgdGhlIHNhdmVkIHJlc3VsdHMKaGVhZChtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJGFsbF9zdGF0cyRrbWVhbnMpCgojIFByZXZpZXcgdGhlIHNhdmVkIHN1bW1hcnkgcmVzdWx0cwpoZWFkKG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkc3VtbWFyeV9zdGF0cyRrbWVhbnMpCmBgYAoKIyMjIyBwdXJpdHkgcGxvdHMKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KIyBQbG90IGluZGl2aWR1YWwgY2x1c3RlciBhbmQgc3VtbWFyeSBzdGF0cwprbWVhbnNfcGxvdHMgPC0gcGxvdF9jbHVzdGVyaW5nX3ZhbGlkaXR5KG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkYWxsX3N0YXRzJGttZWFucywKICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkc3VtbWFyeV9zdGF0cyRrbWVhbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAicHVyaXR5IiwgIm1heGltdW0iLCAiY2x1c3Rlcl9uYW1lcyIsIGMoMjoxNSkpCmttZWFuc19wbG90cwpgYGAKCiMjIyMgc2lsaG91ZXR0ZSB3aWR0aCBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIGFuZCBzdW1tYXJ5IHN0YXRzCmttZWFuc19zaWxob3VldHRlX3Bsb3RzIDwtIHBsb3RfY2x1c3RlcmluZ192YWxpZGl0eShtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJGFsbF9zdGF0cyRrbWVhbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJHN1bW1hcnlfc3RhdHMka21lYW5zLAogICAgICAgICAgICAgICAgICAgICAgICAgIndpZHRoIiwgImNsb3Nlc3QiLCAiY2x1c3Rlcl9uYW1lcyIsIGMoMjoxNSkpCmttZWFuc19zaWxob3VldHRlX3Bsb3RzCmBgYAoKIyMjIGdyYXBoLWJhc2VkLCB3YWxrdHJhcAoKYGBge3IgZmlnLmhlaWdodCA9IDE1LjV9CiMgQ2hlY2sgdGhlIHdhbGt0cmFwIGNsdXN0ZXIgdmFsaWRpdHkgc3RhdHMgZm9yIGVhY2ggb2YgdGhlIGNsdXN0ZXJzIGFuZCBwcm9kdWNlCiMgYSBzdW1tYXJ5IGRhdGEgZnJhbWUgb2YgdGhlc2Ugc3RhdHMgdG8gYmUgc3RvcmVkIHdpdGhpbiB0aGUgU0NFIG9iamVjdApzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gYWRkX21ldGFkYXRhX2NsdXN0ZXJpbmdfc3RhdHMoc2FtcGxlXzI5MF9ub3JtYWxpemVkLCB3YWxrdHJhcF9jbHVzdGVyX25hbWVzLCAid2Fsa3RyYXAiKQogIAojIFByZXZpZXcgdGhlIHNhdmVkIHJlc3VsdHMKaGVhZChtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJGFsbF9zdGF0cyR3YWxrdHJhcCkKCiMgUHJldmlldyB0aGUgc2F2ZWQgc3VtbWFyeSByZXN1bHRzCmhlYWQobWV0YWRhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKSRzdW1tYXJ5X3N0YXRzJHdhbGt0cmFwKQpgYGAKIyMjIyBwdXJpdHkgcGxvdHMKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KIyBQbG90IGluZGl2aWR1YWwgY2x1c3RlciBhbmQgc3VtbWFyeSBzdGF0cwp3YWxrdHJhcF9wbG90cyA8LSBwbG90X2NsdXN0ZXJpbmdfdmFsaWRpdHkobWV0YWRhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKSRhbGxfc3RhdHMkd2Fsa3RyYXAsCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJHN1bW1hcnlfc3RhdHMkd2Fsa3RyYXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAicHVyaXR5IiwgIm1heGltdW0iLCAiY2x1c3Rlcl9uYW1lcyIsIGMoNSwgMTAsIDE1LCAyMCwgMjUsIDUwLCAxMDApKQp3YWxrdHJhcF9wbG90cwpgYGAKCiMjIyMgc2lsaG91ZXR0ZSB3aWR0aCBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQojIFBsb3QgaW5kaXZpZHVhbCBjbHVzdGVyIGFuZCBzdW1tYXJ5IHN0YXRzCndhbGt0cmFwX3NpbGhvdWV0dGVfcGxvdHMgPC0gcGxvdF9jbHVzdGVyaW5nX3ZhbGlkaXR5KG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkYWxsX3N0YXRzJHdhbGt0cmFwLAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKSRzdW1tYXJ5X3N0YXRzJHdhbGt0cmFwLAogICAgICAgICAgICAgICAgICAgICAgICAgIndpZHRoIiwgImNsb3Nlc3QiLCAiY2x1c3Rlcl9uYW1lcyIsIGMoNSwgMTAsIDE1LCAyMCwgMjUsIDUwLCAxMDApKQp3YWxrdHJhcF9zaWxob3VldHRlX3Bsb3RzCmBgYAoKIyMjIGdyYXBoLWJhc2VkLCBsb3V2YWluCgpgYGB7ciBmaWcuaGVpZ2h0ID0gOS41fQojIENoZWNrIHRoZSBsb3V2YWluIGNsdXN0ZXIgdmFsaWRpdHkgc3RhdHMgZm9yIGVhY2ggb2YgdGhlIGNsdXN0ZXJzIGFuZCBwcm9kdWNlCiMgYSBzdW1tYXJ5IGRhdGEgZnJhbWUgb2YgdGhlc2Ugc3RhdHMgdG8gYmUgc3RvcmVkIHdpdGhpbiB0aGUgU0NFIG9iamVjdApzYW1wbGVfMjkwX25vcm1hbGl6ZWQgPC0gYWRkX21ldGFkYXRhX2NsdXN0ZXJpbmdfc3RhdHMoc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBsb3V2YWluX2NsdXN0ZXJfbmFtZXMsICJsb3V2YWluIikKCiMgUHJldmlldyB0aGUgc2F2ZWQgcmVzdWx0cwpoZWFkKG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkYWxsX3N0YXRzJGxvdXZhaW4pCgojIFByZXZpZXcgdGhlIHNhdmVkIHN1bW1hcnkgcmVzdWx0cwpoZWFkKG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkc3VtbWFyeV9zdGF0cyRsb3V2YWluKQpgYGAKIyMjIyBwdXJpdHkgcGxvdHMKCmBgYHtyIGZpZy5oZWlnaHQ9MTB9CiMgUGxvdCBpbmRpdmlkdWFsIGNsdXN0ZXIgYW5kIHN1bW1hcnkgc3RhdHMKbG91dmFpbl9wbG90cyA8LSBwbG90X2NsdXN0ZXJpbmdfdmFsaWRpdHkobWV0YWRhdGEoc2FtcGxlXzI5MF9ub3JtYWxpemVkKSRhbGxfc3RhdHMkbG91dmFpbiwKICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkc3VtbWFyeV9zdGF0cyRsb3V2YWluLAogICAgICAgICAgICAgICAgICAgICAgICAgInB1cml0eSIsICJtYXhpbXVtIiwgImNsdXN0ZXJfbmFtZXMiLCBjKDUsIDEwLCAxNSwgMjAsIDI1LCA1MCwgMTAwKSkKbG91dmFpbl9wbG90cwpgYGAKCiMjIyMgc2lsaG91ZXR0ZSB3aWR0aCBwbG90cwoKYGBge3IgZmlnLmhlaWdodD0xMH0KIyBQbG90IGluZGl2aWR1YWwgY2x1c3RlciBhbmQgc3VtbWFyeSBzdGF0cwpsb3V2YWluX3NpbGhvdWV0dGVfcGxvdHMgPC0gcGxvdF9jbHVzdGVyaW5nX3ZhbGlkaXR5KG1ldGFkYXRhKHNhbXBsZV8yOTBfbm9ybWFsaXplZCkkYWxsX3N0YXRzJGxvdXZhaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YShzYW1wbGVfMjkwX25vcm1hbGl6ZWQpJHN1bW1hcnlfc3RhdHMkbG91dmFpbiwKICAgICAgICAgICAgICAgICAgICAgICAgICJ3aWR0aCIsICJjbG9zZXN0IiwgImNsdXN0ZXJfbmFtZXMiLCBjKDUsIDEwLCAxNSwgMjAsIDI1LCA1MCwgMTAwKSkKbG91dmFpbl9zaWxob3VldHRlX3Bsb3RzCmBgYAoKIyMgQ2hlY2sgY2x1c3RlciBzdGFiaWxpdHkKCiMjIyBrLW1lYW5zCgpgYGB7cn0KIyBDaGVjayBhbmQgcGxvdCBjbHVzdGVyIHN0YWJpbGl0eSBDREYKY2RmIDwtIE5VTEwKZm9yIChuYW1lIGluIGttZWFuc19jbHVzdGVyX25hbWVzKSB7CiAgY2RmW1tuYW1lXV0gPC0gcHJlcGFyZV9wbG90X2NsdXN0ZXJfc3RhYmlsaXR5KHNhbXBsZV8yOTBfbm9ybWFsaXplZCwgbmFtZSkKfQoKY29sb3JzIDwtIHBhbGV0dGUuY29sb3JzKHBhbGV0dGUgPSAiT2thYmUtSXRvIikKCnBsb3QoY2RmW1sia2NsdXN0ZXIyIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBtYWluID0gImtjbHVzdGVyIGNsdXN0ZXIgc3RhYmlsaXR5IENERiIpCnBsb3QoY2RmW1sia2NsdXN0ZXIzIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1sxXSkKcGxvdChjZGZbWyJrY2x1c3RlcjQiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzJdKQpwbG90KGNkZltbImtjbHVzdGVyNSJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbM10pCnBsb3QoY2RmW1sia2NsdXN0ZXI2Il1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1s0XSkKcGxvdChjZGZbWyJrY2x1c3RlcjciXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzVdKQpwbG90KGNkZltbImtjbHVzdGVyOCJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbNl0pCnBsb3QoY2RmW1sia2NsdXN0ZXI5Il1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1s3XSkKcGxvdChjZGZbWyJrY2x1c3RlcjEwIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1s4XSkKcGxvdChjZGZbWyJrY2x1c3RlcjExIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1s5XSkKcGxvdChjZGZbWyJrY2x1c3RlcjEyIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1sxMF0pCnBsb3QoY2RmW1sia2NsdXN0ZXIxMyJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbMTFdKQpwbG90KGNkZltbImtjbHVzdGVyMTQiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzEyXSkKcGxvdChjZGZbWyJrY2x1c3RlcjE1Il1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1sxM10pCmxlZ2VuZCgwLjY1LCAwLjk1LCBsZWdlbmQgPSBhcy5saXN0KGttZWFuc19jbHVzdGVyX25hbWVzKSwgY29sID0gY29sb3JzLCBjZXggPSAwLjUsIHBjaCA9IDE1KQpgYGAKCiMjIyBncmFwaC1iYXNlZCwgd2Fsa3RyYXAKCmBgYHtyfQojIENoZWNrIGFuZCBwbG90IGNsdXN0ZXIgc3RhYmlsaXR5IENERgpjZGYgPC0gTlVMTApmb3IgKG5hbWUgaW4gd2Fsa3RyYXBfY2x1c3Rlcl9uYW1lcykgewogIGNkZltbbmFtZV1dIDwtIHByZXBhcmVfcGxvdF9jbHVzdGVyX3N0YWJpbGl0eShzYW1wbGVfMjkwX25vcm1hbGl6ZWQsIG5hbWUpCn0KCmNvbG9ycyA8LSBwYWxldHRlLmNvbG9ycyhwYWxldHRlID0gIk9rYWJlLUl0byIpWzI6bGVuZ3RoKHdhbGt0cmFwX2NsdXN0ZXJfbmFtZXMpICsgMV0KCnBsb3QoY2RmW1sid2Fsa3RyYXBfY2x1c3RlcjUiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIG1haW4gPSAid2Fsa3RyYXAgY2x1c3RlciBzdGFiaWxpdHkgQ0RGIikKcGxvdChjZGZbWyJ3YWxrdHJhcF9jbHVzdGVyMTAiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzFdKQpwbG90KGNkZltbIndhbGt0cmFwX2NsdXN0ZXIxNSJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbMl0pCnBsb3QoY2RmW1sid2Fsa3RyYXBfY2x1c3RlcjIwIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1szXSkKcGxvdChjZGZbWyJ3YWxrdHJhcF9jbHVzdGVyMjUiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzRdKQpwbG90KGNkZltbIndhbGt0cmFwX2NsdXN0ZXI1MCJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbNV0pCnBsb3QoY2RmW1sid2Fsa3RyYXBfY2x1c3RlcjEwMCJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbNl0pCmxlZ2VuZCgtMywgMC45NSwgbGVnZW5kID0gYXMubGlzdCh3YWxrdHJhcF9jbHVzdGVyX25hbWVzKSwgY29sID0gY29sb3JzLCBjZXggPSAwLjUsIHBjaCA9IDE1KQpgYGAKCiMjIyBncmFwaC1iYXNlZCwgbG91dmFpbgoKYGBge3J9CiMgQ2hlY2sgYW5kIHBsb3QgY2x1c3RlciBzdGFiaWxpdHkgQ0RGCmNkZiA8LSBOVUxMCmZvciAobmFtZSBpbiBsb3V2YWluX2NsdXN0ZXJfbmFtZXMpIHsKICBjZGZbW25hbWVdXSA8LSBwcmVwYXJlX3Bsb3RfY2x1c3Rlcl9zdGFiaWxpdHkoc2FtcGxlXzI5MF9ub3JtYWxpemVkLCBuYW1lKQp9Cgpjb2xvcnMgPC0gcGFsZXR0ZS5jb2xvcnMocGFsZXR0ZSA9ICJPa2FiZS1JdG8iKVsyOmxlbmd0aChsb3V2YWluX2NsdXN0ZXJfbmFtZXMpICsgMV0KCnBsb3QoY2RmW1sibG91dmFpbl9jbHVzdGVyNSJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgbWFpbiA9ICJsb3V2YWluIGNsdXN0ZXIgc3RhYmlsaXR5IENERiIpCnBsb3QoY2RmW1sibG91dmFpbl9jbHVzdGVyMTAiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzFdKQpwbG90KGNkZltbImxvdXZhaW5fY2x1c3RlcjE1Il1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1syXSkKcGxvdChjZGZbWyJsb3V2YWluX2NsdXN0ZXIyMCJdXSwgdmVydGljYWxzPVRSVUUsIGRvLnBvaW50cz1GQUxTRSwgYWRkPVRSVUUsIGNvbD1jb2xvcnNbM10pCnBsb3QoY2RmW1sibG91dmFpbl9jbHVzdGVyMjUiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzRdKQpwbG90KGNkZltbImxvdXZhaW5fY2x1c3RlcjUwIl1dLCB2ZXJ0aWNhbHM9VFJVRSwgZG8ucG9pbnRzPUZBTFNFLCBhZGQ9VFJVRSwgY29sPWNvbG9yc1s1XSkKcGxvdChjZGZbWyJsb3V2YWluX2NsdXN0ZXIxMDAiXV0sIHZlcnRpY2Fscz1UUlVFLCBkby5wb2ludHM9RkFMU0UsIGFkZD1UUlVFLCBjb2w9Y29sb3JzWzZdKQpsZWdlbmQoLTAuMjUsIDAuOTUsIGxlZ2VuZCA9IGFzLmxpc3QobG91dmFpbl9jbHVzdGVyX25hbWVzKSwgY29sID0gY29sb3JzLCBjZXggPSAwLjUsIHBjaCA9IDE1KQpgYGAKCiMjIFNlc3Npb24gaW5mbwoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCg==